/*
*  Copyright (c) 2001 Sun Microsystems, Inc.  All rights
*  reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*  1. Redistributions of source code must retain the above copyright
*  notice, this list of conditions and the following disclaimer.
*
*  2. Redistributions in binary form must reproduce the above copyright
*  notice, this list of conditions and the following discalimer in
*  the documentation and/or other materials provided with the
*  distribution.
*
*  3. The end-user documentation included with the redistribution,
*  if any, must include the following acknowledgment:
*  "This product includes software developed by the
*  Sun Microsystems, Inc. for Project JXTA."
*  Alternately, this acknowledgment may appear in the software itself,
*  if and wherever such third-party acknowledgments normally appear.
*
*  4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
*  must not be used to endorse clor promote products derived from this
*  software without prior written permission. For written
*  permission, please contact Project JXTA at http://www.jxta.org.
*
*  5. Products derived from this software may not be called "JXTA",
*  nor may "JXTA" appear in their name, without prior written
*  permission of Sun.
*
*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
*  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
*  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
*  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
*  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*  SUCH DAMAGE.
*  ====================================================================
*
*  This software consists of voluntary contributions made by many
*  individuals on behalf of Project JXTA.  For more
*  information on Project JXTA, please see
*  <http://www.jxta.org/>.
*
*  This license is based on the BSD license adopted by the Apache Foundation.
*
*  $Id: OneToOneCommandDialog.java,v 1.18 2007/06/10 21:15:11 nano Exp $
*/

package net.jxta.myjxta.dialog;

import net.jxta.endpoint.Message;
import net.jxta.myjxta.MyJXTA;
import net.jxta.myjxta.View;
import net.jxta.myjxta.plugin.PluginView;
import net.jxta.myjxta.util.Group;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.util.JxtaBiDiPipe;

import java.io.IOException;

/**
 * @author james todd [gonzo at jxta dot org]
 * @version $Id: OneToOneCommandDialog.java,v 1.18 2007/06/10 21:15:11 nano Exp $
 */

public class OneToOneCommandDialog
        extends Dialog
        implements PipeMsgListener {

    public static final String IMFREE_COMMAND_NAME = IMFREE + "Command";
    public static final String DIALOG_NAME = IMFREE_COMMAND_NAME;

    /**
     * The timeout to set if creating a JxtaBiDiPipe  pipe
     */
    private static final int MAX_CONNECT_WAIT = 40 * 1000;

    /**
     * The  JxtaBiDiPipe on which to exchange messages
     */
    protected JxtaBiDiPipe pipe = null;
    private static final java.util.logging.Logger MYLOG = java.util.logging.Logger.getLogger(OneToOneCommandDialog.class.getName());

    //exception that may have occured during the pipe binding;
    private IOException pipeException = null;

    /**
     * Create a OneToOneDialog object
     *
     * @param group  the Group in which the Dialog object is active
     * @param pa     the PipeAdvertisement of the peer to which we want to chat
     * @param myJxta the MyJXTA instance to use
     */
    public OneToOneCommandDialog(Group group, PipeAdvertisement pa,
                                 MyJXTA myJxta) {
        this(group, pa, null, myJxta); //this one will create a pipe
    }

    /**
     * Create a OneToOneDialog object
     *
     * @param group  the Group in which the Dialog object
     *               is active
     * @param pipe   the JxtaBiDiPipe on which to exchange messages
     * @param myJxta the MyJXTA instance to use
     */
    public OneToOneCommandDialog(Group group, JxtaBiDiPipe pipe, MyJXTA myJxta) {
        this(group, pipe != null ? pipe.getRemotePipeAdvertisement() : null,
                pipe, myJxta);
    }

    public String getName() {
        return DialogMessage.DEFAULT_ORIGINATOR;
    }

    /**
     * Dispatch a Message object to the intended receivers.
     * This implementation reports the status of the
     * sendMessage method  which is invoked on the Messenger of
     * the JxtaBiDiPipe  instance of this dialog
     *
     * @param msg the Message object to send across an open pipe
     */
    public boolean dispatch(Message msg) {
        boolean isDispatched = false;

        if (this.pipe != null) {
            try {
                isDispatched = this.pipe.sendMessage(msg);
            } catch (IOException ioe) {
                MYLOG.log(java.util.logging.Level.INFO,
                        "dispatching command failed:", ioe);
            }
        }

        return isDispatched;
    }

    // PipeMsgListener methods

    /**
     * Called if a new PipeMsgEvent was received
     *
     * @param pme the triggering PipeMsgEvent object
     */
    public void pipeMsgEvent(PipeMsgEvent pme) {
        receive(pme.getMessage());
    }

    /**
     * Close this dialog object, releasing all associated resources.
     */
    public void close() {
        if (pipe != null) {
            try {
                pipe.close();
            } catch (IOException ioe) {
                //
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public PluginView getDialogPanel(View p_myJXTAView) {
        return null; // no dialog panel, this is a command dialog
    }

    /**
     * Create a OneToOneDialog object
     *
     * @param group  the Group in which the Dialog object
     *               is active
     * @param pa     the PipeAdvertisement of the peer to which we
     *               want to chat
     * @param pipe   the JxtaBiDiPipe on which to exchange messages
     * @param myJxta the MyJXTA instance to use
     */
    protected OneToOneCommandDialog(Group group, PipeAdvertisement pa,
                                    JxtaBiDiPipe pipe, MyJXTA myJxta) {
        super(myJxta, pa, group);

        if (pipe == null) {
            pipe = Cache.getCache(getGroup()).get(getPipeAdvertisement());
        }

        // Create the JxtaBiDiPipe if necessary
        this.pipe=pipe;
        createPipe();

        // update the DialogMessage template to report the
        // correct originator
        DialogMessage dmsg = getDialogMessage();

        dmsg.setLabel(dmsg.getOriginator());

        setDialogMessage(dmsg);
    }

    private void createPipe() {
        if (this.pipe == null) {
            try {
                this.pipe = new JxtaBiDiPipe(getGroup().getPeerGroup(), getPipeAdvertisement(),
                        MAX_CONNECT_WAIT, null);
            } catch (IOException ioe) {
                this.pipeException = ioe;
                //need to dismiss the dialog
            }

        } else {
            //already created
        }
    }

    public void activate() {
        if (this.pipe==null){
            createPipe();    //maybe the pipe creation has failed before - we�ll try again
        }

        if (this.pipe != null) {
            this.pipe.setMessageListener(this);
            Cache.getCache(getGroup()).put(getPipeAdvertisement(), this.pipe);
            setIsConnected(this.pipe.isBound());
        } else {
            setIsConnected(false);
        }
    }

    /**
     * Perform any task  that need to be performed after the
     * Message object was send. This implementation delivers the
     * message back to itself so that the message can be echoed in this
     * Dialog object.
     *
     * @param msg the Message object that was send
     */
    protected void postDispatch(Message msg) {
    }

    /**
     * Perform any tasks that need to be performed before all
     * registered DialogListeners are informed that a new DialogMessage
     * object was received. This implementation sets the
     * label property of dm to the originator if this message
     * was originated by ourself.
     *
     * @param dm the DialogMessage object that was received
     * @return the changed DialogMessage image is any
     */
    protected DialogMessage preReceive(DialogMessage dm) {
        if (!dm.getOriginator().equals(getDialogMessage().getOriginator())) {
            dm.setLabel(dm.getOriginator());
        }

        return dm;
    }

    public IOException getPipeCreationException() {
        return pipeException;
    }
}
